package main

import (
	"flag"
	"fmt"
	"gse/transport/udp/connection"
	"gse/transport/udp/server"
	"hash/crc32"
	"io/ioutil"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"time"
)

var responeChan = make(chan []byte, 1000)

func main() {
	flagset := flag.NewFlagSet("parameters", flag.ExitOnError)
	var sAddr string
	flagset.StringVar(&sAddr, "s", "0.0.0.0:3131", "server address, e.g. 127.0.0.1:3131")
	var connWriteBufferSize, connReadBufferSize int
	flagset.IntVar(&connReadBufferSize, "wb", 1024*1024, "UDP connection read buffer size")
	flagset.IntVar(&connWriteBufferSize, "rb", 1024*1024, "UDP connection write buffer size")
	flagset.Parse(os.Args[1:])

	go http.ListenAndServe("0.0.0.0:6364", nil)
	addr, _ := net.ResolveUDPAddr("udp4", sAddr)
	s, err := net.ListenUDP("udp4", addr)
	if err != nil {
		panic(err)
	}
	fmt.Println("serve on: ", addr.Network(), addr.String())
	cfg := server.NewDefaultUDPServerConfig()
	cfg.ConnectionWriteBufferSize = connWriteBufferSize
	cfg.ConnectionReadBufferSize = connReadBufferSize
	ts := server.NewUDPServer(s, cfg)
	for {
		conn, err := ts.Accept()
		if err != nil {
			panic(err)
		}
		go handleConn(conn)
	}
}

func handleConn(conn *connection.Connection) {
	defer conn.Close()
	go response(conn)
	responeChan <- []byte(fmt.Sprintf("hello %v, you're now connected to GSE, current server time: %v.", conn.RemoteAddr().String(), time.Now()))
	dir := "/tmp/"
	//conn.Send([]byte("ok, you're connected!"))
	for {
		data, err := conn.ReadData()
		if err != nil {
			fmt.Printf("conn read data err: %v", err)
			return
		}
		checksum := crc32.ChecksumIEEE(data)
		fileName := fmt.Sprintf("%v", checksum)
		savePath := dir + fileName
		fmt.Printf("\nread data bytes: %v\n", len(data))
		ioutil.WriteFile(savePath, data, 0666)
		responeChan <- []byte(fmt.Sprintf("received %v bytes, crc_checksum: %v, saved to file: %v", len(data), checksum, savePath))
	}
}

func response(conn *connection.Connection) {
	ticker := time.NewTicker(time.Second * 8)
	var d []byte
	for {
		select {
		case d = <-responeChan:
		case t := <-ticker.C:
			d = []byte(fmt.Sprintf("current server time: %v", t))
		}

		if _, err := conn.SendData(d); err != nil {
			fmt.Println("send error:", err)
			return
		}
	}
}
